class IUP_TREE
-- Creates a tree containing nodes of branches or leaves. Both branches and 
-- leaves can have an associated text and image.
--
-- The branches can be expanded or collapsed. When a branch is expanded, its 
-- immediate children are visible, and when it is collapsed they are hidden.
--
-- The leaves can generate an "executed" or "renamed" actions, branches can 
-- only generate a "renamed" action.
--
-- The focus node is the node with the focus rectangle, marked nodes have their 
-- background inverted.

inherit
	IUP_WIDGET
		undefine
			execute_dragbegin,
			execute_dragdatasize,
			execute_dragdata,
			execute_dragend,
			execute_dropdata,
			execute_dropmotion
		redefine
			execute_map,
			execute_unmap,
			execute_destroy,
			execute_getfocus,
			execute_killfocus,
			execute_enterwindow,
			execute_leavewindow,
			execute_k_any,
			execute_help,
			execute_button,
			execute_motion,
			execute_dropfiles,
			execute_dragdrop,
			execute_rightclick,
			execute_selection,
			execute_multiselection,
			execute_multiunselection,
			execute_branchopen,
			execute_branchclose,
			execute_executeleaf,
			execute_showrename,
			execute_rename,
			execute_noderemoved,
			execute_togglevalue
		end
	IUP_WIDGET_BGCOLOR
	IUP_WIDGET_EXPAND
	IUP_WIDGET_FGCOLOR
	IUP_WIDGET_ACTIVE
	IUP_WIDGET_FONT
	IUP_WIDGET_SCREENPOSITION
	IUP_WIDGET_POSITION
	IUP_WIDGET_MAXMIN_SIZE
	IUP_WIDGET_TIP
	IUP_WIDGET_SIZE
	IUP_WIDGET_RASTERSIZE
	IUP_WIDGET_USERSIZE
	IUP_WIDGET_VISIBLE
	IUP_WIDGET_ZORDER
	IUP_WIDGET_TITLE
	IUP_WIDGET_SPACING
		redefine
			set_spacing
		end
	IUP_WIDGET_CHILD
	IUP_WIDGET_NAME
	IUP_WIDGET_FOCUS
	IUP_WIDGET_PROPAGATEFOCUS
	IUP_DRAG_AND_DROP
	IUP_WIDGET_CUSTOM_ATTRIBUTES

create {ANY}
	tree

feature {ANY}

	tree
		-- A new tree
		local
			a_tree: POINTER
		do
			a_tree := int_tree
			set_widget(a_tree)
		end

	-- General attributes

	set_add_expanded (state: BOOLEAN)
		-- (non inheritable): Defines if branches will be expanded when created. 
		-- The branch will be actually expanded when it receives the first child. 
		-- Possible values: "True" = The branches will be created expanded; 
		-- "False" = The branches will be created collapsed. Default: "True".
		do
			iup_open.set_attribute(Current, "ADDEXPANDED", boolean_to_yesno(state))
		end

	set_add_root (state: BOOLEAN)
		-- (non inheritable): automatically adds an empty branch as the first 
		-- node when the tree is mapped. Default: "True".
		do
			iup_open.set_attribute(Current, "ADDROOT", boolean_to_yesno(state))
		end

	set_auto_redraw (state: BOOLEAN)
		-- [Windows] (non inheritable): automatically redraws the tree when 
		-- something has change. Set to False to add many items to the tree 
		-- without updating the display. Default: "True".
		do
			iup_open.set_attribute(Current, "AUTOREDRAW", boolean_to_yesno(state))
		end

	set_can_focus (state: BOOLEAN)
		-- (creation only) (non inheritable): enables the focus traversal of the 
		-- control. In Windows the control will still get the focus when clicked. 
		-- Default: True.
		do
			iup_open.set_attribute(Current, "CANFOCUS", boolean_to_yesno(state))
		end

	set_drag_drop_tree (state: BOOLEAN)
		-- (non inheritable): enable or disable the drag and drop of nodes 
		-- between trees, in the same IUP application. Drag & Drop attributes 
		-- must be set in order to activate the drag & drop support. On the other 
		-- hand, it is not necessary to register drag & drop callbacks. 
		-- Default: False.
		do
			iup_open.set_attribute(Current, "DRAGDROPTREE", boolean_to_yesno(state))
		end

	set_as_drop_files_target (state: BOOLEAN)
		-- [Windows and GTK Only] (non inheritable): Enable or disable the drop 
		-- of files. Default: False, but if DROPFILES_CB is defined when the 
		-- element is mapped then it will be automatically enabled. This is NOT 
		-- related to the drag&drop of nodes inside the tree.
		do
			iup_open.set_attribute(Current, "DROPFILESTARGET", boolean_to_yesno(state))
		end

	set_drop_equal_drag (state: BOOLEAN)
		-- (non inheritable): if enabled will allow a drop node to be equal to 
		-- the drag node. Used only if SHOWDRAGDROP = True. In the case the nodes 
		-- are equal the callback return value is ignored and nothing is done 
		-- after.	
		do
			iup_open.set_attribute(Current, "DROPEQUALDRAG", boolean_to_yesno(state))
		end

	set_empty_as_3state (state: BOOLEAN)
		-- (non inheritable) [Windows Only]: when SHOWTOGGLE=True, the empty 
		-- space left in nodes that NODEVISIBLEid=False is filled with the image 
		-- of the 3state toggle. Can be True or False. Default: False.
		do
			iup_open.set_attribute(Current, "EMPTYAS3STATE", boolean_to_yesno(state))
		end

	set_hide_buttons (state: BOOLEAN)
		-- (creation only): hide the expand and collapse buttons. In GTK, 
		-- branches will be only expanded programmatically. In Motif it did not 
		-- work and crash the test.
		do
			iup_open.set_attribute(Current, "HIDEBUTTONS", boolean_to_yesno(state))
		end

	set_hide_lines (state: BOOLEAN)
		-- (creation only): hide the lines that connect the nodes in the 
		-- hierarchy.	
		do
			iup_open.set_attribute(Current, "HIDELINES", boolean_to_yesno(state))
		end

	set_rgb_highlight_color (red: INTEGER; green: INTEGER; blue: INTEGER)
		-- [Windows and Motif Only] (non inheritable): the background color of 
		-- the selected node. Default: TXTHLCOLOR global attribute.
		do
			iup_open.set_attribute(Current, "HLCOLOR", rgb_to_string(red, green, blue))
		end

	set_hexadecimal_highlight_color (color: STRING)
		-- Same as set_rgb_hlcolor but usign an hexadecimal 
		-- value (#RRGGBB).
		local
			tup: TUPLE[INTEGER, INTEGER, INTEGER]
		do
			tup := hexadecimal_to_rgb(color)
			set_rgb_highlight_color(tup.item_1, tup.item_2, tup.item_3)
		end

	reset_highlight_color
		-- Reset the background color of the selected node.
		do
			iup_open.reset_attribute(Current, "HLCOLOR")
		end

	set_indentation (value: INTEGER)
		-- Sets the indentation level in pixels. The visual effect of changing 
		-- the indentation is highly system dependent. In GTK it acts as an 
		-- additional indent value, and the lines do not follow the extra indent. 
		-- In Windows is limited to a minimum of 5 pixels.
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "INDENTATION", value.to_string)
		end

	set_info_tip (state: BOOLEAN)
		-- [Windows Only]: the TIP is shown every time an item is highlighted. 
		-- This is the default behavior for TIPs in native tree controls in 
		-- Windows, if set to False then it will use the regular TIP behavior. 
		-- Default: True.
		do
			iup_open.set_attribute(Current, "INFOTIP", boolean_to_yesno(state))
		end

	set_show_drag_drop (state: BOOLEAN)
		-- (creation only) (non inheritable): Enables the internal drag and drop 
		-- of nodes, and enables the DRAGDROP_CB callback. Default: "False". 
		-- Works only if MARKMODE=SINGLE.
		do
			iup_open.set_attribute(Current, "SHOWDRAGDROP", boolean_to_yesno(state))
		end

	set_show_toggle (state: STRING)
		-- (creation only) (non inheritable): enables the use of toggles for all 
		-- nodes of the tree. Can be "YES", "3STATE" or NO". Default: "NO". In 
		-- Motif Versions 2.1.x and 2.2.x, the images are disabled (toggle and 
		-- text only are drawn in nodes of the tree).
		do
			iup_open.set_attribute(Current, "SHOWTOGGLE", state)
		end

	set_spacing (value: INTEGER)
		-- vertical internal padding for each node. Notice that the distance 
		-- between each node will be actually 2x the spacing. 
		do
			Precursor (value)
		end

	set_top_item (value: INTEGER)
		-- (write-only): position the given node identifier at the top of the 
		-- tree or near to make it visible. If any parent node is collapsed then 
		-- they are automatically expanded.
		do
			iup_open.set_attribute(Current, "TOPITEM", value.to_string)
		end

	-- Attributes for nodes

	get_count: INTEGER
		-- (read only) (non inheritable): returns the total number of nodes in 
		-- the tree.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "COUNT")
			if str.is_integer then
				Result := str.to_integer
			end
		end

	get_child_count_at (id: INTEGER): INTEGER
		require
			id >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id(Current, "CHILDCOUNT", id)

			if str.is_integer then
				Result := str.to_integer
			end
		end
	
	get_total_child_count_at (id: INTEGER): INTEGER
		-- (read only): returns the total children count of the specified branch. 
		-- It counts all grandchildren.
		require
			id >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id(Current, "TOTALCHILDCOUNT", id)

			if str.is_integer then
				Result := str.to_integer
			end
		end

	get_root_count: INTEGER
		-- Returns the number of root nodes.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "ROOTCOUNT")

			if str.is_integer then
				Result := str.to_integer
			end
		end

	set_rgb_color_at (red, green, blue, id: INTEGER;)
		-- Text foreground color of the specified node. The value should be a 
		-- string in the format "R G B" 
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "COLOR", id, rgb_to_string(red, green, blue))
		end

	get_depth_at (id: INTEGER): INTEGER
		-- (read only): returns the depth of the specified node. The first node 
		-- has depth=0, its immediate children has depth=1, their children has 
		-- depth=2 and so on.
		require
			id >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id(Current, "DEPTH", id)
			
			if str.is_integer then
				Result := str.to_integer
			end
		end

	get_kind_at (id: INTEGER): STRING
		--  (read only): returns the kind of the specified node. Possible values:
		--
		-- "LEAF": The node is a leaf
		-- "BRANCH": The node is a branch
		require
			id >= 0
		do
			Result := iup_open.get_attribute_id(Current, "KIND", id)
		end

	get_parent_at (id: INTEGER): INTEGER
		-- (read only): returns the identifier of the specified node.
		require
			id >= 0
		local
			str: STRING
		do
			str := iup_open.get_attribute_id(Current, "PARENT", id)
			
			if str.is_integer then
				Result := str.to_integer
			end
		end

	get_next_at (id: INTEGER): STRING
		-- Returns the next brother (same depth) of the specified node. Returns 
		-- an empty string if at last child node of the parent (at the same
      -- depth).
		require
			id >= 0
		do
			Result := iup_open.get_attribute_id(Current, "NEXT", id)
		end

	get_previous_at (id: INTEGER): STRING
		-- Returns the previous brother (same depth) of the specified node. 
		-- Returns an empty string if at first child node of the parent (at the 
		-- same depth).
		require
			id >= 0
		do
			Result := iup_open.get_attribute_id(Current, "PREVIOUS", id)
		end

	get_last_at (id: INTEGER): STRING
		-- Returns the last brother (same depth) of the specified node.
		require
			id >= 0
		do
			Result := iup_open.get_attribute_id(Current, "LAST", id)
		end

	get_first_at (id: INTEGER): STRING
		-- Returns the first brother (same depth) of the specified node. This is 
		-- the same as getting the first child of the parent of the given node.
		require
			id >= 0
		do
			Result := iup_open.get_attribute_id(Current, "FIRST", id)
		end

	set_state_at (state: STRING; id: INTEGER)
		require
			is_valid_state(state)
			id >= 0
		do
			iup_open.set_attribute_id(Current, "STATE", id, state)
		end

	get_state_at (id: INTEGER): STRING
		-- The state of the specified branch. Returns Void for a LEAF. 
		require
			id >= 0
		do
			Result := iup_open.get_attribute_id(Current, "STATE", id)	
		end

	set_title_at (title: STRING; id: INTEGER)
		-- The text label of the specified node.
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "TITLE", id, title)
		end

	get_title_at (id: INTEGER): STRING
		-- The text label of the specified node.
		require
			id >= 0
		do
			Result := iup_open.get_attribute_id(Current, "TITLE", id)
		end

	set_title_font_at (font: STRING; id: INTEGER)
		-- The text font of the specified node. The format is the same 
		-- used at set_font.
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "TITLEFONT", id, font)
		end

	set_title_font_style_at (style: STRING; id: INTEGER)
		-- Changes the font style of the specified node.
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "TITLEFONTSTYLE", id, style)
		end

	set_title_font_size_at (size, id: INTEGER)
		-- Changes the font size of the specified node.
		require
			size > 0
			id >= 0
		do
			iup_open.set_attribute_id(Current, "TITLEFONTSIZE", id, size.to_string)
		end

	set_toggle_value_at (value: STRING; id: INTEGER)
		-- (non inheritable): defines the toggle state. Values can be "ON" or 
		--"OFF". If SHOW3STATE=True then can also be "NOTDEF". Default: "OFF".
		require
			is_valid_toggle (value)
			id >= 0
		do
			iup_open.set_attribute_id(Current, "VALUE", id, value)
		end

	set_toggle_visible_at (state: BOOLEAN; id: INTEGER)
		-- (non inheritable): defines the toggle visible state.
		-- Default: "True".
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "TOGGLEVISIBLE", id, boolean_to_yesno(state))
		end

	set_user_data_at (data: STRING; id: INTEGER)
		-- The user data associated with the specified node.
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "USERDATA", id, data)
		end

	get_user_data_at (id: INTEGER): STRING
		-- The user data associated with the specified node.
		require
			id >= 0
		do
			Result := iup_open.get_attribute_id(Current, "USERDATA", id)
		end

	-- Attributes for images

	set_image_at (image: STRING; id: INTEGER)
		-- (write only): image name to be used in the specified node, where id is 
		-- the specified node identifier. Use set_attribute_handle to associate 
		-- an image to a name. See also IUP_IMAGE. In Windows and Motif set the 
		-- BGCOLOR attribute before setting the image. If node is a branch it is 
		-- used when collapsed.
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "IMAGE", id, image)
		end

	set_image_expanded_at (image: STRING; id: INTEGER)
		-- (write only): same as the IMAGE attribute but used for expanded 
		-- branches.
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "IMAGEEXPANDED", id, image)
		end

	set_image_leaf(image: STRING)
		-- The image name that will be shown for all leaves. Default: "IMGLEAF". 
		-- Internal values "IMGBLANK" and "IMGPAPER" are also available. If 
		-- BGCOLOR is set the image is automatically updated.
		do
			iup_open.set_attribute(Current, "IMAGELEAF", image)
		end

	set_image_branch_collapsed (image: STRING)
		-- The image name that will be shown for all collapsed branches. 
		-- Default: "IMGCOLLAPSED". If BGCOLOR is set the image is automatically 
		-- updated.
		do
			iup_open.set_attribute(Current, "IMAGEBRANCHCOLLAPSED", image)
		end

	set_image_branch_expanded (image: STRING)
		-- The image name that will be shown for all expanded branches. 
		-- Default: "IMGEXPANDED". If BGCOLOR is set the image is automatically 
		-- updated.
		do
			iup_open.set_attribute(Current, "IMAGEBRANCHEXPANDED", image)
		end

	-- Attributes for node

	set_value (id: INTEGER)
		-- (non inheritable): The focus node identifier. When changed and 
		-- MARKMODE=SINGLE the node is also selected. The tree is always scrolled 
		-- so the node becomes visible. In Motif the tree will also receive the 
		-- focus.
		require
			id >= 0
		do
			iup_open.set_attribute(Current, "VALUE", id.to_string)
		end

	get_value: INTEGER
		-- (non inheritable): The focus node identifier. When retrieved but 
		-- there isn't a node with focus it returns 0 if there are any nodes, and 
		-- returns -1 if there are no nodes. 
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "VALUE")

			if str.is_integer then
				Result := str.to_integer
			end
		end

	-- Special operations for nodes

	select_first
		-- The first node.
		do
			iup_open.set_attribute(Current, "VALUE", "FIRST")
		end

	select_last
		-- The last node.
		do
			iup_open.set_attribute(Current, "VALUE", "LAST")
		end

	select_next
		-- The next node.
		do
			iup_open.set_attribute(Current, "VALUE", "NEXT")
		end

	select_previous
		-- The previous node.
		do
			iup_open.set_attribute(Current, "VALUE", "PREVIOUS")
		end

	select_page_down
		-- The next visible node, ten nodes after the focus node. If at the last 
		-- does nothing.
		do
			iup_open.set_attribute(Current, "VALUE", "PGDN")
		end

	select_page_up
		-- The previous visible node, ten nodes before the focus node. If at the 
		-- first does nothing.
		do
			iup_open.set_attribute(Current, "VALUE", "PGUP")
		end

	clear
		-- Clears the selection of the focus node.
		do
			iup_open.set_attribute(Current, "VALUE", "CLEAR")
		end

	-- Attributes to marks

	set_mark (first, last: INTEGER)
		-- (write only) (non inheritable): Selects a range of nodes in the 
		-- format "first-last". Allowed only when MARKMODE=MULTIPLE.
		require
			first >= 0
			last >= 0
		local
			str: STRING
		do
			str := first.to_string
			str.append_string("-")
			str.append_string(last.to_string
									)
			iup_open.set_attribute(Current, "MARK", str)	
		end

	invert_mark_at (id: INTEGER)
		-- Inverts the specified node selected state, where id is the specified 
		-- node identifier. If id is empty or invalid, then the focus node is 
		-- used as reference node. 
		require
			id >= 0
		local
			str: STRING
		do
			str := "INVERT"
			str.append_string(id.to_string)
			
			iup_open.set_attribute(Current, "MARK", str)
		end

	mark_block
		-- Selects all nodes between the focus node and the initial block-marking 
		-- node defined by set_mark_start.
		do
			iup_open.set_attribute(Current, "MARK", "BLOCK")
		end

	clear_all
		-- Clear the selection of all nodes.
		do
			iup_open.set_attribute(Current, "MARK", "CLEARALL")
		end

	mark_all
		--  Selects all nodes.
		do
			iup_open.set_attribute(Current, "MARK", "MARKALL")
		end

	invert_all
		-- Inverts the selection of all nodes.
		do
			iup_open.set_attribute(Current, "MARK", "INVERTALL")
		end

	set_marked_at (state: BOOLEAN; id: INTEGER)
		-- (non inheritable): The selection state of the specified node, where id 
		-- is the specified node identifier. If id is empty or invalid, then the 
		-- focus node is used as reference node. State can be: True or False. 
		-- Default: False.
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "MARKED", id, boolean_to_yesno(state))
		end

	get_marked_at (id: INTEGER): BOOLEAN
		-- Get the marked state at the specified node.
		local
			str: STRING
		do
			str := iup_open.get_attribute_id(Current, "MARKED", id)
			Result := yesno_to_boolean(str)
		end

	set_marked_nodes (value: STRING)
		-- (non inheritable): The selection state of all nodes when 
		-- MARKMODE=MULTIPLE. It accepts a sequence of '+' and '-' symbols 
		-- indicating the state of each item ('+'=selected, '-'=unselected. When 
		-- setting this value, if the number of specified symbols is smaller than 
		-- the total count then the remaining nodes will not be changed.
		do
			iup_open.set_attribute(Current, "MARKEDNODES", value)
		end

	get_marked_nodes: STRING
		-- The selection state of the nodes. It is a sequence of '+' and '-' 
		-- symbols indicating the state of each item ('+'=selected, 
		-- '-'=unselected.	
		do
			Result := iup_open.get_attribute(Current, "MARKEDNODES")
		end

	set_mark_mode (value: STRING)
		-- Defines how the nodes can be selected. Can be: SINGLE or MULTIPLE. 
		-- Default: SINGLE.
		require
			is_valid_mode(value)
		do
			iup_open.set_attribute(Current, "MARKMODE", value)	
		end

	set_mark_start (id: INTEGER)
		-- (non inheritable): Defines the initial node for the block marking, used
		-- in mark_block. The value must be the node identifier. Default: 0 
		-- (first node).
		require
			id >= 0
		do
			iup_open.set_attribute(Current, "MARKSTART", id.to_string)	
		end

	set_mark_when_toggle (state: BOOLEAN)
		-- (non inheritable) [GTK and Windows Only]: selects or clears the 
		-- selection of a node when its toggle is changed. Works only if the node 
		-- has a toggle. Default: False.
		do
			iup_open.set_attribute(Current, "MARKWHENTOGGLE", boolean_to_yesno(state))
		end

	-- Hierarchy attributes

	add_leaf_at (value: STRING; id: INTEGER)
		-- (write only): Adds a new leaf after the reference node, where id is 
		-- the reference node identifier. Use id = -1 to add before the first 
		-- node. The value is used as the text label of the new node. The id of 
		-- the new node will be the id of the reference node + 1. The attribute 
		-- LASTADDNODE is set to the new id. The reference node is marked and all 
		-- others unmarked. The reference node position remains the same. If the 
		-- reference node does not exist, nothing happens. If the reference node 
		-- is a branch then the depth of the new node is one depth increment from 
		-- the depth of the reference node, if the reference node is a leaf then 
		-- the new node has the same depth. If you need to add a node after a 
		-- specified node but at a different depth use insert_leaf_at. Ignored if 
		-- set before map. 
		require
			id >= -2
		do
			iup_open.set_attribute_id(Current, "ADDLEAF", id, value)
		end

	get_last_added_node: INTEGER
		-- The id of tha last added node.
		local
			str: STRING
		do
			str := iup_open.get_attribute(Current, "LASTADDNODE")

			if str.is_integer then
				Result := str.to_integer
			end
		end

	add_branch_at (value: STRING; id: INTEGER)
		-- (write only): Same as add_leaf_at for branches. Branches can be 
		-- created expanded or collapsed depending on set_add_expanded. Ignored 
		-- if set before map.
		require
			id >= -2
		do
			iup_open.set_attribute_id(Current, "ADDBRANCH", id, value)
		end

	copy_node_to (node_id, target_id: INTEGER)
		-- (write only): Copies a node and its children, where node_id is the 
		-- specified node identifier. The target_id is the destination node 
		-- identifier. If the destination node is a branch and it is expanded, 
		-- then the specified node is inserted as the first child of the 
		-- destination node. If the branch is not expanded or the destination 
		-- node is a leaf, then it is inserted as the next brother of the leaf. 
		-- The specified node is not changed. All node attributes are copied, 
		-- except user data. Ignored if set before map.
		require
			node_id >= 0
			target_id >= 0
		do
			iup_open.set_attribute_id(Current, "COPYNODE", node_id, target_id.to_string)
		end

	delete_all_nodes
		-- Deletes all nodes.
		do
			iup_open.set_attribute_id(Current, "DELNODE", 1, "ALL")
		end

	delete_node_at (id: INTEGER)
		-- Deletes the specified node and its children (if any).
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "DELNODE", id, "SELECTED")
		end

	delete_node_children_at (id: INTEGER)
		-- Deletes only the children of the specified node.
		require
			id >= 0
		do
			iup_open.set_attribute_id(Current, "DELNODE", id, "CHILDREN")
		end

	delete_selected_nodes
	   -- Deletes all the selected nodes (and all their children),
		do
			iup_open.set_attribute_id(Current, "DELNODE", 1, "MARKED")
		end

	expand_all
		-- (write only): expand all nodes.
		do
			iup_open.set_attribute(Current, "EXPANDALL", "YES")
		end

	contract_all
		-- (write only): contracts all nodes.
		do
			iup_open.set_attribute(Current, "EXPANDALL", "NO")
		end

	insert_leaf_at (value: STRING; id: INTEGER)
		-- (write only): Same as add_leaf but the depth of the new node is always 
		-- the same of the reference node. If the reference node is a leaf, then 
		-- the id of the new node will be the id of the reference node + 1. If 
		-- the reference node is a branch the id of the new node will be the id 
		-- of the reference node + 1 + the total number of child nodes of the 
		-- reference node. 
		require
			id >= -2
		do
			iup_open.set_attribute_id(Current, "INSERTLEAF", id, value)
		end

	insert_branch_at (value: STRING; id: INTEGER)
		-- (write only): Same as insert_leaf_at for branches. Branches can be 
		-- created expanded or collapsed depending on set_add_expanded. Ignored 
		-- if set before map.
		require
			id >= -2
		do
			iup_open.set_attribute_id(Current, "INSERTBRANCH", id, value)
		end

	move_node_at (node_id, target_id: INTEGER)
		-- (write only): Moves a node and its children, where node_id is the 
		-- specified node identifier. The target_id is the destination node 
		-- identifier. If the destination node is a branch and it is expanded, 
		-- then the specified node is inserted as the first child of the 
		-- destination node. If the branch is not expanded or the destination 
		-- node is a leaf, then it is inserted as the next brother of the leaf. 
		-- The specified node is removed. User data and all node attributes are 
		-- preserved. Ignored if set before map.
		require
			node_id >= 0
			target_id >= 0
		do
			iup_open.set_attribute_id(Current, "MOVENODE", node_id, target_id.to_string)
		end

	-- Editing attributes

	start_rename
		-- (write only): Forces a rename action to take place. Valid only when 
		-- set_show_rename = True.	
		do
			iup_open.set_attribute(Current, "RENAME", "YES")
		end

	set_rename_position (position: INTEGER)
		-- (write only): the caret’s position of the text box when in-place 
		-- renaming. The first position is "1". Used only once after 
		-- SHOWRENAME_CB is called and before the text box is shown.
		require
			position >= 1
		do
			iup_open.set_attribute(Current, "RENAMEPOSITION", position.to_string)
		end

	set_rename_selection (col1, col2: INTEGER)
		-- (write only): the selection interval of the text box when in-place 
		-- renaming. Used only once after SHOWRENAME_CB is called and before the 
		-- text box is shown.
		--
		-- Selection interval in characters. Where col1 and col2 are integer 
		-- numbers corresponding to the selection's interval. col2 correspond to 
		-- the character after the last selected character.
		-- In Windows, when changing the selection the caret position is also 
		-- changed.	
		local
			str: STRING
		do
			create str.copy(col1.to_string)
	      str.append_string(":")
 	      str.append_string(col2.to_string)
	
			iup_open.set_attribute(Current, "RENAMESELECTION", str)
		end

	set_show_rename (state: BOOLEAN)
		-- (creation in Windows) (non inheritable): Allows the in place rename of 
		-- a node. Default: "False". Since IUP 3.0, F2 and clicking twice only 
		-- starts to rename a node if SHOWRENAME=True. In Windows must be set to 
		-- True before map, but can be changed later.
		do
			iup_open.set_attribute(Current, "SHOWRENAME", boolean_to_yesno(state))
		end

	-- Coordination to pos
	convert_xy_to_pos (x, y: INTEGER): INTEGER
		-- Converts a (x,y) coordinate in a node position.
		-- Returns: a node identifier starting at 0. If fails returns -1.
		do
			Result := iup_open.iup_convert_xy_to_pos (Current, x, y)	
		end

	-- Callbacks

	-- Common
	set_cb_map (act: FUNCTION[TUPLE[IUP_TREE], STRING])
		-- Called right after an element is mapped and its attributes updated.
		local
			operation: INTEGER
		do
			cb_map := act
			
			if cb_map /= Void then
				operation := 1
			else
				operation := 0
			end
						
			iup_open.set_callback (Current, "MAP_CB", "NONEEDED", operation)
		end

	set_cb_unmap (act: FUNCTION[TUPLE[IUP_TREE], STRING])
		-- Called right before an element is unmapped.
		local
			operation: INTEGER
		do
			cb_unmap := act

			if cb_unmap /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "UNMAP_CB", "NONEEDED", operation)
		end

	set_cb_destroy (act: FUNCTION[TUPLE[IUP_TREE], STRING])
		-- Called right before an element is destroyed.
		local
			operation: INTEGER
		do
			cb_destroy := act

			if cb_destroy /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DESTROY_CB", "NONEEDED", operation)
		end

	set_cb_get_focus (act: FUNCTION[TUPLE[IUP_TREE], STRING])
		-- Action generated when an element is given keyboard focus. 
		-- This callback is called after the KILLFOCUS_CB of the element 
		-- that loosed the focus. The {IUP}.get_focus function during the 
		-- callback returns the element that loosed the focus.
		local
			operation: INTEGER
		do
			cb_getfocus := act

			if cb_getfocus /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "GETFOCUS_CB", "NONEEDED", operation)
		end

	set_cb_kill_focus (act: FUNCTION[TUPLE[IUP_TREE], STRING])
		-- Action generated when an element loses keyboard focus. This 
		-- callback is called before the GETFOCUS_CB of the element that 
		-- gets the focus.
		local
			operation: INTEGER
		do
			cb_killfocus := act

			if cb_killfocus /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "KILLFOCUS_CB", "NONEEDED", operation)
		end

	set_cb_enter_window (act: FUNCTION[TUPLE[IUP_TREE], STRING])
		-- Action generated when the mouse enters the native element. 
		local
			operation: INTEGER
		do
			cb_enterwindow := act

			if cb_enterwindow /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "ENTERWINDOW_CB", "NONEEDED", operation)
		end

	set_cb_leave_window (act: FUNCTION[TUPLE[IUP_TREE], STRING])
		-- Action generated when the mouse leaves the native element.
		local
			operation: INTEGER
		do
			cb_leavewindow := act

			if cb_leavewindow /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "LEAVEWINDOW_CB", "NONEEDED", operation)
		end

	set_cb_k_any (act: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING])
		-- Action generated when a keyboard event occurs.
		-- IUP_WIDGET the element that activated the event.
		-- INTEGER identifier of typed key. Please refer to the Keyboard 
		-- Codes table for a list of possible values.
		--
		-- Returns: If IUP_IGNORE is returned the key is ignored and not
		-- processed by the control and not propagated. If returns 
		-- IUP_CONTINUE, the key will be processed and the event will be
		-- propagated to the parent of the element receiving it, this is 
		-- the default behavior. If returns IUP_DEFAULT the key is processed 
		-- but it is not propagated. IUP_CLOSE will be processed. 
		local
			operation: INTEGER
		do
			cb_k_any := act

			if cb_k_any /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "K_ANY", "NONEEDED", operation)
		end

	set_cb_help (act: PROCEDURE[TUPLE[IUP_TREE]])
		-- Action generated when the user press F1 at a control. In Motif 
		-- is also activated by the Help button in some workstations 
		-- keyboard.
		-- Returns: IUP_CLOSE will be processed.
		local
			operation: INTEGER
		do
			cb_help := act

			if cb_help /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "HELP_CB", "NONEEDED", operation)
		end

	-- Extra
	set_cb_button (act: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when any mouse button is pressed and when it is 
		-- released. Both calls occur before the ACTION callback when button 1 is 
		-- being used.
		--
		-- IUP_BUTTON: identifies the element that activated the event.
		-- button: identifies the activated mouse button:
		--
		-- 1 - left mouse button (button 1);
		-- 2 - middle mouse button (button 2);
		-- 3 - right mouse button (button 3).
		--
		-- pressed: indicates the state of the button:
		--
		-- 0 - mouse button was released;
		-- 1 - mouse button was pressed.
		-- 
		-- x, y: position in the canvas where the event has occurred, in pixels.
		--
		-- status: status of the mouse buttons and some keyboard keys at the 
		-- moment the event is generated. The following IUP features must be used 
		-- for verification:
	   --
		-- is_shift(status)
		-- is_control(status)
		-- is_button_1(status)
		-- is_button_2(status)
		-- is_button_3(status)
		-- is_button_4(status)
		-- is_button_5(status)
		-- is_double(status)
		-- is_alt(status)
		-- is_sys(status)
		--
		-- Returns: IUP_CLOSE will be processed. On some controls if IUP_IGNORE 
		-- is returned the action is ignored (this is system dependent).	
		local
			operation: INTEGER
		do
			cb_button := act

			if cb_button /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "BUTTON_CB", "NONEEDED", operation)
		end

	set_cb_motion (act: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when the mouse moves.
		-- ih: identifier of the element that activated the event.
		-- x, y: position in the canvas where the event has occurred, in pixels.
		-- status: status of mouse buttons and certain keyboard keys at the 
		-- moment the event was generated. The same macros used for BUTTON_CB can 
		-- be used for this status.
		local
			operation: INTEGER
		do
			cb_motion := act

			if cb_motion /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MOTION_CB", "NONEEDED", operation)
		end

	set_cb_drop_files (act: FUNCTION[TUPLE[IUP_TREE, STRING, INTEGER, INTEGER, INTEGER], STRING])
		-- [Windows and GTK Only]: Action generated when one or more files are 
		-- dropped in the element.
		-- If defined after the element is mapped then the attribute 
		-- DROPFILESTARGET must be set to YES. [Windows and GTK Only] 
		local
			operation: INTEGER
		do
			cb_dropfiles := act

			if cb_dropfiles /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DROPFILES_CB", "NONEEDED", operation)
		end

	set_cb_drag_drop (act: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER, INTEGER, INTEGER], STRING])
		-- Action generated when an internal drag and drop is executed. Only 
		-- active if SHOWDRAGDROP=True.
		--
		-- ih: identifier of the element that activated the event.
		-- drag_id: Identifier of the clicked item where the drag start.
		-- drop_id: Identifier of the clicked item where the drop were executed. 
		-- -1 indicates a drop in a blank area.
		-- isshift: flag indicating the shift key state.
		-- iscontrol: flag indicating the control key state.
		--
		-- Returns: if returns IUP_CONTINUE, or if the callback is not defined 
		-- and SHOWDRAGDROP=True, then the node is moved to the new position. If 
		-- Ctrl is pressed then the node is copied instead of moved. If the drop 
		-- node is a branch and it is expanded, then the drag node is inserted as 
		-- the first child of the node. If the branch is not expanded or the node 
		-- is a leaf, then the drag node is inserted as the next brother of the 
		-- drop node.
		local
			operation: INTEGER
		do
			cb_dragdrop := act

			if cb_dragdrop /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DRAGDROP_CB", "NONEEDED", operation)
		end

	set_cb_right_click (act: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING])
		-- Action generated when the right mouse button is pressed over a node.
		--
		-- ih: identifier of the element that activated the event.
		-- id: node identifier. 
		local
			operation: INTEGER
		do
			cb_rightclick := act

			if cb_rightclick /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "RIGHTCLICK_CB", "NONEEDED", operation)
		end

	set_cb_selection (act: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER], STRING])
		-- Action generated when a node is selected or deselected. This action 
		-- occurs when the user clicks with the mouse or uses the keyboard with 
		-- the appropriate combination of keys. It may be called more than once 
		-- for the same node with the same status.
		--
		-- ih: identifier of the element that activated the event.
		-- id: Node identifier.
		-- status: 1=node selected, 0=node unselected. 
		local
			operation: INTEGER
		do
			cb_selection := act

			if cb_selection /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "SELECTION_CB", "NONEEDED", operation)
		end

	set_cb_multi_selection (act: FUNCTION[TUPLE[IUP_TREE, POINTER, INTEGER], STRING])
		--  Action generated after a continuous range of nodes is selected in one 
		-- single operation. If not defined the SELECTION_CB with status=1 will 
		-- be called for all nodes in the range. The range is always completely 
		-- included, independent if some nodes were already marked. That single 
		-- operation also guaranties that all other nodes outside the range are 
		-- already not selected. Called only if MARKMODE=MULTIPLE.
		--
		-- ih: identifier of the element that activated the event.
		-- ids: Array of node identifiers. This array is kept for backward 
		-- compatibility, the range is simply defined by ids[0] to ids[n-1], 
		-- where ids[i+1]=ids[i]+1.
		-- n: Number of nodes in the array.
		local
			operation: INTEGER
		do
			cb_multiselection := act

			if cb_multiselection /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MULTISELECTION_CB", "NONEEDED", operation)
		end

	set_cb_multi_unselection (act: FUNCTION[TUPLE[IUP_TREE, POINTER, INTEGER], STRING])
		local
			operation: INTEGER
		do
			cb_multiunselection := act

			if cb_multiunselection /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MULTIUNSELECTION_CB", "NONEEDED", operation)
		end

	set_cb_branch_open (act: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING])
		-- Action generated when a branch is expanded. This action occurs when 
		-- the user clicks the "+" sign on the left of the branch, or when double 
		-- clicks the branch, or hits Enter on a collapsed branch.
		--
		-- ih: identifier of the element that activated the event.
		-- id: node identifier.
		--
		-- Returns: IUP_IGNORE for the branch not to be opened, or IUP_DEFAULT 
		-- for the branch to be opened.
		local
			operation: INTEGER
		do
			cb_branchopen := act

			if cb_branchopen /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "BRANCHOPEN_CB", "NONEEDED", operation)
		end

	set_cb_branch_close (act: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING])
		-- Action generated when a branch is collapsed. This action occurs when 
		-- the user clicks the "-" sign on the left of the branch, or when double 
		-- clicks the branch, or hits Enter on an expanded branch.
		--
		-- ih: identifier of the element that activated the event.
		-- id: node identifier.
		--
		-- Returns: IUP_IGNORE for the branch not to be closed, or IUP_DEFAULT 
		-- for the branch to be closed.
		local
			operation: INTEGER
		do
			cb_branchclose := act

			if cb_branchclose /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "BRANCHCLOSE_CB", "NONEEDED", operation)
		end

	set_cb_execute_leaf (act: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING])
		-- Action generated when a leaf is to be executed. This action occurs 
		-- when the user double clicks a leaf, or hits Enter on a leaf. 
		--
		-- ih: identifier of the element that activated the event.
		-- id: node identifier.	
		local
			operation: INTEGER
		do
			cb_executeleaf := act

			if cb_executeleaf /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "EXECUTELEAF_CB", "NONEEDED", operation)
		end

	set_cb_show_rename (act: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING])
		-- Action generated when a node is about to be renamed. It occurs when 
		-- the user clicks twice the node or press F2. Called only if 
		-- SHOWRENAME=True.
		--
		-- ih: identifier of the element that activated the event.
		-- id: node identifier. 
		--
		-- Returns: if IUP_IGNORE is returned, the rename is canceled (in GTK the 
		-- rename continuous but the edit box is read-only).
		local
			operation: INTEGER
		do
			cb_showrename := act

			if cb_showrename /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "SHOWRENAME_CB", "NONEEDED", operation)
		end

	set_cb_rename (act: FUNCTION[TUPLE[IUP_TREE, INTEGER, STRING], STRING])
		-- Action generated after a node was renamed in place. It occurs when the 
		-- user press Enter after editing the name, or when the text box looses 
		-- it focus. Called only if SHOWRENAME=True.
		--
		-- ih: identifier of the element that activated the event.
		-- id: node identifier.
		-- title: new node title.
		--
		-- Returns: The new title is accepted only if the callback returns 
		-- IUP_DEFAULT. If the callback does not exists the new title is always 
		-- accepted. If the user pressed Enter and the callback returns 
		-- IUP_IGNORE the editing continues. If the text box looses its focus the 
		-- editing stops always.
		local
			operation: INTEGER
		do
			cb_rename := act

			if cb_rename /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "RENAME_CB", "NONEEDED", operation)
		end

	set_cb_node_removed (act: FUNCTION[TUPLE[IUP_TREE, STRING], STRING])
		-- Action generated when a node is going to be removed. It is only a 
		-- notification, the action can not be aborted. No node dependent 
		-- attribute can be consulted during the callback. Not called when the 
		-- tree is unmapped. It is useful to remove memory allocated for the 
		-- userdata.
		--
		-- ih: identifier of the element that activated the event.
		-- userdata/userid: USERDATA attribute in C.
		local
			operation: INTEGER
		do
			cb_noderemoved := act

			if cb_noderemoved /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "NODEREMOVED_CB", "NONEEDED", operation)
		end

	set_cb_toggle_value (act: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER], STRING])
		-- Action generated when the toggle's state was changed. The callback 
		-- also receives the new toggle's state.
		--
		-- ih: identifier of the element that activated the event.
		-- id: node identifier.
		-- state: 1 if the toggle's state was shifted to ON; 0 if it was shifted 
		-- to OFF. If SHOW3STATE=YES, −1 if it was shifted to NOTDEF.
		local
			operation: INTEGER
		do
			cb_togglevalue := act

			if cb_togglevalue /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "TOGGLEVALUE_CB", "Fnii", operation)
		end
	

feature {IUP}

	-- Common callbacks
	
	execute_map: STRING
		do
			Result := cb_map.item([Current])
		end

	execute_unmap: STRING
		do
			Result := cb_unmap.item([Current])
		end

	execute_destroy: STRING
		do
			Result := cb_destroy.item([Current])
		end

	execute_getfocus: STRING
		do
			Result := cb_getfocus.item([Current])
		end

	execute_killfocus: STRING
		do
			Result := cb_getfocus.item([Current])
		end

	execute_enterwindow: STRING
		do
			Result := cb_enterwindow.item([Current])
		end

	execute_leavewindow: STRING
		do
			Result := cb_leavewindow.item([Current])
		end

	execute_k_any (c: INTEGER): STRING
		do
			Result := cb_k_any.item([Current, c])
		end

	execute_help
		do
			cb_help.call([Current])
		end

	-- Extra
	
	execute_button (btn, pressed, x, y: INTEGER; status: STRING): STRING
		do
			Result := cb_button.item([Current, btn, pressed, x, y, status])
		end

	execute_motion (x, y: INTEGER; status: STRING): STRING
		do
			Result := cb_motion.item([Current, x, y, status])
		end

	execute_dropfiles (filename: STRING; num: INTEGER; x: INTEGER; y: INTEGER): STRING
		do
			Result := cb_dropfiles.item([Current, filename, num, x, y])
		end

	execute_dragdrop (drag_id, drop_id, isshift, iscontrol: INTEGER): STRING
		do
			Result := cb_dragdrop.item([Current, drag_id, drop_id, isshift, iscontrol])
		end

	execute_rightclick (id: INTEGER): STRING
		do
			Result := cb_rightclick.item([Current, id])
		end

	-- Others

	execute_selection (id, status: INTEGER): STRING
		do
			Result := cb_selection.item([Current, id, status])
		end

	execute_multiselection (ids: POINTER; n: INTEGER): STRING
		do
			Result := cb_multiselection.item([Current, ids, n])
		end

	execute_multiunselection (ids: POINTER; n: INTEGER): STRING
		do
			Result := cb_multiunselection.item([Current, ids, n])
		end

	---------------

	execute_branchopen (id: INTEGER): STRING
		do
			Result := cb_branchopen.item([Current, id])
		end

	execute_branchclose (id: INTEGER): STRING
		do
			Result := cb_branchclose.item([Current, id])
		end

	execute_executeleaf (id: INTEGER): STRING
		do
			Result := cb_executeleaf.item([Current, id])
		end

	-------------------

	execute_showrename (id: INTEGER): STRING
		do
			Result := cb_showrename.item([Current, id])
		end

	execute_rename (id: INTEGER; title: STRING): STRING
		do
			Result := cb_rename.item([Current, id, title])
		end

	-------------------

	execute_noderemoved (userdata: POINTER): STRING
		local
			str: STRING
		do
			if userdata.is_not_null then
				create str.from_external_copy(userdata)
			else
				str := ""
			end
				
			Result := cb_noderemoved.item([Current, str])
		end

	-------------------

	execute_togglevalue (id, state: INTEGER): STRING
		do
			Result := cb_togglevalue.item([Current, id, state])
		end

	
feature {}
	
	-- For callbacks

	cb_map: FUNCTION[TUPLE[IUP_TREE], STRING]
	cb_unmap: FUNCTION[TUPLE[IUP_TREE], STRING]
	cb_destroy: FUNCTION[TUPLE[IUP_TREE], STRING]
	cb_getfocus: FUNCTION[TUPLE[IUP_TREE], STRING]
	cb_killfocus: FUNCTION[TUPLE[IUP_TREE], STRING]
	cb_enterwindow: FUNCTION[TUPLE[IUP_TREE], STRING]
	cb_leavewindow: FUNCTION[TUPLE[IUP_TREE], STRING]
	cb_k_any: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING]
	cb_help: PROCEDURE[TUPLE[IUP_TREE]]

	cb_button: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING]
	cb_motion: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER, STRING], STRING]
	cb_dropfiles: FUNCTION[TUPLE[IUP_TREE, STRING, INTEGER, INTEGER, INTEGER], STRING]
	cb_dragdrop: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER, INTEGER, INTEGER], STRING]
	cb_rightclick: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING]

	cb_selection: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER], STRING]
	cb_multiselection: FUNCTION[TUPLE[IUP_TREE, POINTER, INTEGER], STRING]
	cb_multiunselection: FUNCTION[TUPLE[IUP_TREE, POINTER, INTEGER], STRING]

	cb_branchopen: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING]
	cb_branchclose: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING]
	cb_executeleaf: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING]

	cb_showrename: FUNCTION[TUPLE[IUP_TREE, INTEGER], STRING]
	cb_rename: FUNCTION[TUPLE[IUP_TREE, INTEGER, STRING], STRING]

	cb_noderemoved: FUNCTION[TUPLE[IUP_TREE, STRING], STRING]

	cb_togglevalue: FUNCTION[TUPLE[IUP_TREE, INTEGER, INTEGER], STRING]
	
	-- Internal

	int_tree: POINTER
		external "plug_in"
      alias "{
         location: "${sys}/plugins"
         module_name: "iup"
         feature_name: "IupTree()"
         }"
      end

	-- Validations

	is_valid_state (value: STRING): BOOLEAN
		do
			if value.is_equal("EXPANDED") or
				value.is_equal("COLLAPSED") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_toggle (value: STRING): BOOLEAN
		do
			if value.is_equal("ON") or
				value.is_equal("OFF") or
				value.is_equal("NOTDEF") then
				Result := True
			else
				Result := False
			end
		end

	is_valid_mode (value: STRING): BOOLEAN
		do
			if value.is_equal("SINGLE") or
				value.is_equal("MULTIPLE") then
				Result := True
			else
				Result := False
			end
		end

end

-- The MIT License (MIT)

-- Copyright (c) 2016, 2017, 2018 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
